
// <copyright file="GenericDataReaderStrategy.cs" company="Subhadra Software Solutions">
//   
// </copyright>
// <summary>
//   The read next callback.
// </summary>

namespace SubhadraSolutions.Sharp.Utils.Data
{
    using System;
    using System.Collections.Generic;

    /// <summary>
    /// The read next callback.
    /// </summary>
    /// <typeparam name="T">
    /// </typeparam>
    public delegate T ReadNextCallback<out T>();

    /// <summary>
    /// The populate item array delegate.
    /// </summary>
    /// <param name="obj">
    /// The obj.
    /// </param>
    /// <param name="itemArray">
    /// The item array.
    /// </param>
    /// <typeparam name="T">
    /// </typeparam>
    public delegate void PopulateItemArrayDelegate<in T>(T obj, object[] itemArray);

    /// <summary>
    /// The dispose delegate.
    /// </summary>
    public delegate void DisposeDelegate();

    /// <summary>
    /// The generic data reader strategy.
    /// </summary>
    /// <typeparam name="T">
    /// </typeparam>
    public class GenericDataReaderStrategy<T> : AbstractDataReaderStrategy<T>
        where T : class
    {
        #region Fields

        /// <summary>
        /// The columns.
        /// </summary>
        private readonly IList<KeyValuePair<string, Type>> _columns;

        /// <summary>
        /// The dispose callback.
        /// </summary>
        private readonly DisposeDelegate _disposeCallback;

        /// <summary>
        /// The populate item array delegate.
        /// </summary>
        private readonly PopulateItemArrayDelegate<T> _populateItemArrayDelegate;

        /// <summary>
        /// The read next callback.
        /// </summary>
        private readonly ReadNextCallback<T> _readNextCallback;

        #endregion Fields

        #region Constructors and Finalizers

        /// <summary>
        /// Initializes a new instance of the <see cref="GenericDataReaderStrategy{T}"/> class.
        /// </summary>
        /// <param name="columns">
        /// The columns.
        /// </param>
        /// <param name="readNextCallback">
        /// The read next callback.
        /// </param>
        /// <param name="populateItemArrayDelegate">
        /// The populate item array delegate.
        /// </param>
        /// <param name="disposeCallback">
        /// The dispose callback.
        /// </param>
        public GenericDataReaderStrategy(IList<KeyValuePair<string, Type>> columns, ReadNextCallback<T> readNextCallback, PopulateItemArrayDelegate<T> populateItemArrayDelegate, DisposeDelegate disposeCallback)
        {
            this._columns = columns;
            this._readNextCallback = readNextCallback;
            this._populateItemArrayDelegate = populateItemArrayDelegate;
            this._disposeCallback = disposeCallback;
        }

        #endregion Constructors and Finalizers

        #region Methods

        /// <summary>
        /// The dispose.
        /// </summary>
        /// <param name="disposing">
        /// The disposing.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (this._disposeCallback != null)
            {
                this._disposeCallback();
            }
        }

        /// <summary>
        /// The get columns.
        /// </summary>
        /// <returns>
        /// The <see cref="IList"/>.
        /// </returns>
        protected override IList<KeyValuePair<string, Type>> getColumns()
        {
            return this._columns;
        }

        /// <summary>
        /// The populate item array.
        /// </summary>
        /// <param name="obj">
        /// The obj.
        /// </param>
        /// <param name="itemArray">
        /// The item array.
        /// </param>
        protected override void populateItemArray(T obj, object[] itemArray)
        {
            this._populateItemArrayDelegate(obj, itemArray);
        }

        /// <summary>
        /// The read next object.
        /// </summary>
        /// <returns>
        /// The <see cref="T"/>.
        /// </returns>
        protected override T readNextObject()
        {
            return this._readNextCallback();
        }

        #endregion Methods
    }
}